export async function mockChooseImage() {
  let fs = wx.getFileSystemManager()
  if (!global.__minium_mock_choose_image) {
      // 未注入过, 注入相关方法
      /**
       * 重写 chooseImage & chooseMedia
       * 
       * @param {*} wx        wx实例
       * @param {*} filePath  文件路径
       * @param {*} size      文件大小
       */
      async function rewriteChooseImage(wx, filePath, size) {
          // 重写 chooseImage & chooseMedia
          const ori = {}
          const descriptor = {}
          const mockFunction = {
              chooseImage(obj) {
                  release()
                  const res = {
                      errMsg: "chooseImage:ok",
                      tempFilePaths: [filePath],
                      tempFiles: [
                          { path: filePath, size: size }
                      ]
                  }
                  if (!obj.success && !obj.fail && !obj.complete) return Promise.resolve(res)
                  obj.success && obj.success(res)
                  obj.complete && obj.complete(res)
              },
              chooseMedia(obj) {
                  release()
                  const res = {
                      errMsg: "chooseMedia:ok",
                      tempFiles: [{
                          tempFilePath: filePath,
                          size: size,
                          fileType: "image"
                      }],
                      type: "image"
                  }
                  if (!obj.success && !obj.fail && !obj.complete) return Promise.resolve(res)
                  obj.success && obj.success(res)
                  obj.complete && obj.complete(res)
              }
          }
          const interfaces = Object.keys(mockFunction)
          interfaces.forEach((method) => {
              ori[method] = wx[method]
              descriptor[method] = Object.getOwnPropertyDescriptor(wx, method)
          })
          function release() {
              interfaces.forEach((method) => {
                  if (descriptor[method]) {
                      if (!descriptor[method].get) {
                          Object.defineProperty(wx, method, {
                              writable: true,
                              value: ori[method]
                          })
                      } else {
                          Object.defineProperty(wx, method, {
                              configurable: true,
                              get: () => ori[method]
                          })
                      }

                  } else {
                      wx[method] = ori[method]
                  }
              })
          }

          interfaces.forEach((method) => {
              if (descriptor[method]) {
                  if (!descriptor[method].get) {
                      Object.defineProperty(wx, method, {
                          writable: true,
                          value: mockFunction[method]
                      })
                  } else {
                      Object.defineProperty(wx, method, {
                          configurable: true,
                          get: () => mockFunction[method]
                      })
                  }
              } else {
                  wx[method] = mockFunction[method]
              }
          })
      }
      /**
       * 调用chooseImage & chooseMedia前先调用，可替换将要选取的图片内容. 
       * 暴露到global.__minium_mock_choose_image
       * 
       * @param {{imageData?: string, imageName: string, size?: number}} params 
       * @returns 
       */
      global.__minium_mock_choose_image = async function (params) {
          // imageData should be base64 string
          const { imageData, imageName, size } = params
          const filePath = `${wx.env.USER_DATA_PATH}/.MINIUM/${imageName}`
          if (!imageData || imageData.length === 0) {
              // 已经有文件了
              await rewriteChooseImage(wx, filePath, size)
              return {
                  imageName,
                  size
              }
          }
          // 需要写入内容
          return await new Promise((resolve, reject) => {
              fs.writeFile({
                  filePath: filePath,
                  data: imageData,
                  encoding: "base64",
                  success: async () => {  // mock chooseImage & chooseMedia
                      fs.stat({
                          path: filePath,
                          success: async ({ stats }) => {
                              await rewriteChooseImage(wx, filePath, stats.size)
                              resolve({
                                  imageName,
                                  size: stats.size
                              })
                          }
                      })
                  },
                  fail: ({ errMsg }) => {
                      if (errMsg === 'writeFile:fail the maximum size of the file storage limit is exceeded') {
                          reject('小程序文件空间不足')
                      } else if (errMsg === 'writeFile:fail sdcard not mounted') {
                          reject('sdcard未挂载')
                      } else {
                          reject(`Mock失败: ${errMsg}`)
                      }
                  }
              })
          })
      }
  }
  return new Promise((resolve, reject) => {
      fs.stat({ 
          path: `${wx.env.USER_DATA_PATH}/.MINIUM/`, 
          recursive: true, 
          success: res => {
            if (!res.stats.length) {
              // not array
              return resolve([])
            }
            resolve(res.stats.map((v) => {return {
              name: v.path.replace(/^\//, ""),
              size: v.stats.size
            }}).filter(v => v.name))
          },
          fail: ({errMsg}) => {
            if (errMsg.indexOf("no such file or directory") >= 0) {
              fs.mkdir({
                dirPath: `${wx.env.USER_DATA_PATH}/.MINIUM`,
                recursive: true,
                success() {
                  resolve([])
                },
                fail: reject
              })
            }
          }
      })
  })
}